package com.api.volunteer.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.api.volunteer.dto.UserDTO;
import com.api.volunteer.model.LoginAbsent;
import com.api.volunteer.model.LoginTokenEntity;
import com.api.volunteer.model.Status;
import com.api.volunteer.model.UserEntity;
import com.api.volunteer.repository.LoginTokenRepository;
import com.api.volunteer.repository.UserRepository;
import com.api.volunteer.ro.TokenAbsent;
import com.api.volunteer.ro.UserCode;
import com.api.volunteer.service.LoginTokenService;
import com.api.volunteer.util.Holder;
import com.api.volunteer.util.JWTUtil;
import com.api.volunteer.util.Result;
import com.api.volunteer.util.WXUtils;
import com.api.volunteer.vo.UserDataVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import javax.transaction.Synchronization;
import javax.transaction.Transactional;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author 邹宇杰
 * @email 2901570623@qq.com
 * @date 2022/3/30 14:59
 */
@Service("loginTokenService")
@Transactional(rollbackOn = Exception.class)
public class LoginTokenServiceImpl implements LoginTokenService {

    @Autowired
    LoginTokenRepository loginTokenRepository;

    @Autowired
    UserRepository userRepository;

    @Autowired
    Holder holder;

    private final Lock lock = new ReentrantLock();

    private final Logger logger = LoggerFactory.getLogger(LoginTokenServiceImpl.class);

    /**
     * 用户进入获取token
     * @param userCode
     * @return
     */
    @Override
    public TokenAbsent getToken(UserCode userCode) {

        LoginTokenEntity loginTokenEntity = new LoginTokenEntity();
        String token = JWTUtil.createToken(userCode.getOpenid(), userCode.getSession_key());
        loginTokenEntity.setToken(token);
        loginTokenEntity.setOpenid(userCode.getOpenid());
        loginTokenEntity.setSessionKey(userCode.getSession_key());
        loginTokenRepository.save(loginTokenEntity);

        TokenAbsent tokenAbsent = new TokenAbsent();
        tokenAbsent.setLoginAbsent(LoginAbsent.LOGINHISTORY);

        lock.lock();
        try{
            Optional.ofNullable(userRepository.findUserEntityByOpenid(userCode.getOpenid())).orElseGet(()->{
                //需要再去判断是否第一次进入否则无需补全
                UserEntity userEntity = new UserEntity();
                userEntity.setOpenid(userCode.getOpenid());
                userEntity.setSessionKey(userCode.getSession_key());
                userRepository.save(userEntity);
                tokenAbsent.setLoginAbsent(LoginAbsent.NOLOGINHISTORY);
                return userEntity;
            });
        }catch (Exception e){
            logger.error(e.getMessage());
        }finally {
            lock.unlock();
        }

        tokenAbsent.setToken(token);
        tokenAbsent.setSessionKey(userCode.getSession_key());
        return tokenAbsent;
    }


    @Override
    public Result processData(UserDataVo userDataVo) {

        Result result = new Result();

        UserEntity userEntity = userRepository.findUserEntityByOpenid(holder.getUser().getOpenid());

        synchronized (this) {
            //如果第二次采集信息成功
            if(Objects.equals(userEntity.getSecondSubmit(), Status.Seccess)){
                if(Objects.equals(userEntity.getThirdSubmit(), Status.Seccess)){
                    return result.put("code", 203).put("message", "所有信息采集过了");
                }else{
                    return result.put("code", 202).put("message", "第二次信息采集过了");
                }
            }else{
                UserDTO userDTO = JSONObject.parseObject(WXUtils.decryptData(userDataVo.getEncryptedData(), userDataVo.getSessionKey(), userDataVo.getIv()), UserDTO.class);

                userEntity.setGender(userDTO.getGender());
                userEntity.setAvatarUrl(userDTO.getAvatarUrl());
                userEntity.setLanguage(userDTO.getLanguage());
                userEntity.setAvatarUrl(userDTO.getAvatarUrl());
                userEntity.setNickName(userDTO.getNickName());
                userEntity.setSecondSubmit(Status.Seccess);
                userEntity.setAccountSource(userDataVo.getAccountSource());

                userRepository.save(userEntity);
                result.put("code", 201).put("message", "第二次信息采集成功");
                return result;
            }
        }
    }
}
